package com.lrkj.payfee.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.lrkj.common.constant.FeeConstants;
import com.lrkj.common.constant.OrgConstants;
import com.lrkj.common.exception.BaseException;
import com.lrkj.common.utils.DateUtils;
import com.lrkj.common.utils.LrkjDateUtil;
import com.lrkj.common.utils.uuid.IdUtils;
import com.lrkj.payfee.domain.ChargeNorm;
import com.lrkj.payfee.domain.ChargeTime;
import com.lrkj.payfee.domain.RoomNorm;
import com.lrkj.payfee.domain.RuleCost;
import com.lrkj.payfee.domain.vo.RoomNormVo;
import com.lrkj.payfee.factory.PayFeeFactory;
import com.lrkj.payfee.mapper.RoomNormMapper;
import com.lrkj.payfee.mapper.RuleCostMapper;
import com.lrkj.payfee.service.IChargeNormService;
import com.lrkj.payfee.service.IChargeTimeService;
import com.lrkj.payfee.service.IRoomNormService;
import com.lrkj.payfee.service.IRuleCostService;
import com.lrkj.payfee.vo.CurrentPeriodFeeVo;
import com.lrkj.payfee.vo.NormChargeVo;
import com.lrkj.property.domain.Community;
import com.lrkj.property.domain.Room;
import com.lrkj.property.service.ICommunityService;
import com.lrkj.property.service.IRoomService;
import com.lrkj.waitress.mapper.RoomCustomMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.ParseException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 房屋收费标准Service业务层处理
 *
 * @author yajun_ren
 * @date 2021-07-29
 */
@Service
public class RoomNormServiceImpl implements IRoomNormService {
    @Autowired
    private RoomNormMapper roomNormMapper;

    @Autowired
    private IRoomService roomService;

    @Autowired
    private IChargeNormService chargeNormService;

    @Autowired
    private PayFeeFactory payFeeFactory;

    @Autowired
    private IChargeTimeService chargeTimeService;

    @Autowired
    private ICommunityService communityService;

    @Autowired
    private RuleCostMapper ruleCostMapper;
    /**
     * 查询房屋收费标准
     *
     * @param roomNormId 房屋收费标准ID
     * @return 房屋收费标准
     */
    @Override
    public RoomNorm selectRoomNormById(String roomNormId) {
        return roomNormMapper.selectRoomNormById(roomNormId);
    }

    /**
     * 查询房屋收费标准列表
     *
     * @param roomNorm 房屋收费标准
     * @return 房屋收费标准
     */
    @Override
    public List<RoomNorm> selectRoomNormList(RoomNorm roomNorm) {
        return roomNormMapper.selectRoomNormList(roomNorm);
    }

    /**
     * 查询房屋收费标准列表（不关联其他表的信息）
     *
     * @param roomNorm 房屋收费标准
     * @return 房屋收费标准
     */
    @Override
    public List<RoomNorm> findByList(RoomNorm roomNorm) {
        return roomNormMapper.findByList(roomNorm);
    }

    /**
     * 新增房屋收费标准
     *
     * @param roomNorm 房屋收费标准
     * @return 结果
     */
    @Override
    public int insertRoomNorm(RoomNormVo roomNorm) {
        List<RoomNorm> roomNorms = roomNorm.getRoomNorms();
        List<Room> rooms = this.getSelectRoomList(roomNorm);
        Map<String, Object> roomNormMap = this.getRoomNormMap(roomNorm);
        String communityId = "-1";
        if (rooms.size() > 0) {
            communityId = rooms.get(0).getCommunityId();
        }
        Community community = communityService.selectCommunityById(communityId);
        Date fiscalPeriod = DateUtil.parse(LrkjDateUtil.getMinMonthDate(community.getFiscalPeriod()+"-01"), "yyyy-MM-dd");
        Map<String, ChargeNorm> chargeNormMap = chargeNormService.getChargeNormMap(communityId);
//        //检查计费开始时间
//        this.checkFiscalPeriod(roomNorms, communityId, chargeNormMap);
        List<RoomNorm> saveRoomNormList = new ArrayList<>();
        rooms.stream().forEach(room -> {
            roomNorms.stream().forEach(norm -> {
                RoomNorm bean = new RoomNorm();
                //房间ID+项目类型ID+费用项目ID+费用标准ID
                String key = room.getId() + norm.getProjectId() + norm.getChargeId() + norm.getNormId();
                if (!roomNormMap.containsKey(key)) {
                    bean.setRoomNormId(IdUtils.simpleUUID());
                    bean.setProjectId(norm.getProjectId());
                    bean.setChargeId(norm.getChargeId());
                    bean.setNormId(norm.getNormId());
                    bean.setBeginChargeTime(norm.getBeginChargeTime());
                    bean.setFinishChargetime(norm.getFinishChargetime());
                    bean.setAmountSpecified(norm.getAmountSpecified());
                    bean.setDeptId(room.getDeptId());
                    bean.setCommunityId(room.getCommunityId());
                    bean.setFloorId(room.getFloorId());
                    bean.setUnitId(room.getUnitId());
                    bean.setRoomId(room.getId());
                    bean.setAncestors(room.getAncestors() + "," + room.getId());
                    bean.setStatus(FeeConstants.room_norm_status_10001);
                    bean.setDeliveryTime(LrkjDateUtil.addDay(norm.getBeginChargeTime(), -1));
                    //入住计算下一次生成费用开始时间--》结束时间
                    if (null != bean.getBeginChargeTime() && chargeNormMap.containsKey(norm.getNormId())) {
                        bean.setNextBeginChargeTime(norm.getBeginChargeTime());
                        ChargeNorm chargeNorm = chargeNormMap.get(norm.getNormId());
                        if (chargeNorm.getChargeGenerateType().equals(FeeConstants.charge_generate_type_10)) {
                            bean.setNextFinishChargetime(LrkjDateUtil.getLastMonthDay(bean.getBeginChargeTime()));//下一次结束收费时间
                        } else if (chargeNorm.getChargeGenerateType().equals(FeeConstants.charge_generate_type_20)) {
                            //顺延周期
                            bean.setNextFinishChargetime(DateUtil.offsetDay(DateUtil.offsetMonth(bean.getBeginChargeTime(), 1), -1));//下一次结束收费时间
                        }
                    }
                    //入住计算下一次生成费用开始时间--》结束时间
//                    if (null != bean.getBeginChargeTime() && chargeNormMap.containsKey(norm.getNormId())) {
//                        ChargeNorm chargeNorm = chargeNormMap.get(norm.getNormId());
//                        String fiscal_period=community.getFiscalPeriod();
//                        Date begin_Charge_time=bean.getBeginChargeTime();
//                        //自然周期
//                        if (chargeNorm.getChargeGenerateType().equals(FeeConstants.charge_generate_type_10)) {
//                            //自然周期判断开始收费时间小于当前账期月份
//                            try {
//                                boolean date_boolean=LrkjDateUtil.compareDate(LrkjDateUtil.getFormatTimeString(begin_Charge_time,"yyyy-MM"),fiscal_period,"yyyy-MM");
//                                //开始收费时间<账期时  入住时下一次结束收费时间使用当前账期
//                                if (date_boolean==true){
//                                    bean.setNextFinishChargetime(LrkjDateUtil.getLastMonthDay(fiscalPeriod));//下一次结束收费时间
//                                }else {
//                                    //开始收费时间>账期时  入住时下一次结束收费时间使用开始收费时间最后一天
//                                    bean.setNextFinishChargetime(LrkjDateUtil.getLastMonthDay(bean.getBeginChargeTime()));//下一次结束收费时间
//                                }
//                            }catch (ParseException e) {
//                                e.printStackTrace();
//                            }
//                            //x.setNextFinishChargetime(LrkjDateUtil.getLastMonthDay(x.getBeginChargeTime()));//下一次结束收费时间
//                            //入住时下一次结束收费时间使用当前账期
//                            //x.setNextFinishChargetime(LrkjDateUtil.getLastMonthDay(fiscalPeriod));//下一次结束收费时间
//                        } else if (chargeNorm.getChargeGenerateType().equals(FeeConstants.charge_generate_type_20)) {
//                            //顺延周期判断开始收费时间小于当前账期月份
//                            try {
//                                boolean date_boolean=LrkjDateUtil.compareDate(LrkjDateUtil.getFormatTimeString(begin_Charge_time,"yyyy-MM"),fiscal_period,"yyyy-MM");
//                                //开始收费时间<账期时  入住时下一次结束收费时间使用当前账期
//                                if (date_boolean==true){
//                                    bean.setNextFinishChargetime(LrkjDateUtil.getLastMonthDay(fiscalPeriod));//下一次结束收费时间
//                                }else {
//                                    //开始收费时间>账期时  入住时下一次结束收费时间使用开始收费时间顺延
//                                    /*long poorMonth = DateUtil.betweenMonth(bean.getBeginChargeTime(), fiscalPeriod, true);
//                                    Date offPoorMonthDate = DateUtil.offsetMonth(bean.getBeginChargeTime(), (int) poorMonth + 1);
//                                    */
//                                    Date offPoorMonthDate = DateUtil.offsetMonth(bean.getBeginChargeTime(),  1);
//                                    bean.setNextFinishChargetime(DateUtil.offsetDay(offPoorMonthDate, -1));//下一次结束收费时间
//                                }
//                            }catch (ParseException e) {
//                                e.printStackTrace();
//                            }
//                            //x.setNextFinishChargetime(DateUtil.offsetDay(DateUtil.offsetMonth(x.getBeginChargeTime(), 1), -1));//下一次结束收费时间
//                            //x.setNextFinishChargetime(DateUtil.offsetDay(offPoorMonthDate, -1));//下一次结束收费时间
//                        }
//                    }
                    saveRoomNormList.add(bean);
                }
            });
        });

        return this.doSaveList(saveRoomNormList);
    }

    //检查计费开始时间是否在大于当前账期
    @Override
    public void checkFiscalPeriod(List<RoomNorm> roomNorms, String communityId, Map<String, ChargeNorm> chargeNormMap) {
        StringBuffer msg = new StringBuffer();
        Community community = communityService.selectCommunityById(communityId);//小区信息
        roomNorms.stream().forEach(x -> {
            //计费开始时间不等于空
            if (null != x.getBeginChargeTime()) {
                ChargeNorm chargeNorm = chargeNormMap.get(x.getNormId());
                //检查设置的计费开始时间必须大于等于当前账期
                Date fiscalPeriodDate = DateUtil.parse(LrkjDateUtil.getMinMonthDate(community.getFiscalPeriod()), "yyyy-MM-dd");
                if (!(x.getBeginChargeTime().getTime() >= fiscalPeriodDate.getTime())) {
                    msg.append(chargeNorm.getNormNames());
                    msg.append(",");
                }
            }
        });
        if (msg.length() > 0) {
            msg.deleteCharAt(msg.length() - 1);
            throw new BaseException(String.format("收费标准[%s]计费开始时间小于当前费用期间,请重新设置计费时间。", msg.toString()));
        }
    }

    @Override
    public int updteByRoomId(RoomNorm roomNorm) {
        return roomNormMapper.updteByRoomId(roomNorm);
    }

    @Override
    public int selRoomNormByRoomId(String roomId) {
        return roomNormMapper.selRoomNormByRoomId(roomId);
    }



    //获取房屋列表
    private List<Room> getSelectRoomList(RoomNormVo roomNorm) {
        Room eg = new Room();
        if (OrgConstants.community.equals(roomNorm.getModelType())) {
            eg.setCommunityId(roomNorm.getNodeId());
        } else if (OrgConstants.floor.equals(roomNorm.getModelType())) {
            eg.setFloorId(roomNorm.getNodeId());
        } else if (OrgConstants.room.equals(roomNorm.getModelType())) {
            eg.setId(roomNorm.getNodeId());
        }
        return roomService.selectRoomList(eg);
    }

    //通过节点ID获取已存在的收费标准
    private Map<String, Object> getRoomNormMap(RoomNormVo roomNorm) {
        Map<String, Object> map = new HashMap<>();
        RoomNorm eg = new RoomNorm();
        eg.setNodeId(roomNorm.getNodeId());
        List<RoomNorm> roomNorms = roomNormMapper.selectRoomNormList(eg);
        roomNorms.stream().forEach(x -> {
            //房间ID+项目类型ID+费用项目ID+费用标准ID
            String key = x.getRoomId() + x.getProjectId() + x.getChargeId() + x.getNormId();
            map.put(key, x);
        });
        return map;

    }

    @Override
    public int doSaveList(List<RoomNorm> batchBean) {
        List<RoomNorm> saveBeans = new ArrayList<>();
        if (batchBean.size() > 500) {
            for (int i = 0; i < batchBean.size(); i++) {
                if ((i + 1) % 500 == 0) {
                    saveBeans.add(batchBean.get(i));
                    roomNormMapper.doSaveList(saveBeans);
                    saveBeans.clear();
                } else {
                    saveBeans.add(batchBean.get(i));
                }
            }
            if (null != saveBeans && saveBeans.size() > 0) {
                roomNormMapper.doSaveList(saveBeans);
            }
        } else {
            if (batchBean.size() > 0) {
                roomNormMapper.doSaveList(batchBean);
            }
        }
        return 1;
    }

    @Override
    public int updateByBatchByRoom(List<RoomNorm> batchBean) {
        return roomNormMapper.updateByBatchByRoom(batchBean);
    }



    @Override
    public int updateByBatch(List<RoomNorm> batchBean) {
        List<RoomNorm> saveBeans = new ArrayList<>();
        if (batchBean.size() > 500) {
            for (int i = 0; i < batchBean.size(); i++) {
                if ((i + 1) % 500 == 0) {
                    saveBeans.add(batchBean.get(i));
                    roomNormMapper.updateByBatch(saveBeans);
                    saveBeans.clear();
                } else {
                    saveBeans.add(batchBean.get(i));
                }
            }
            if (null != saveBeans && saveBeans.size() > 0) {
                roomNormMapper.updateByBatch(saveBeans);
            }
        } else {
            if (batchBean.size() > 0) {
                roomNormMapper.updateByBatch(batchBean);
            }
        }
        return 1;
    }

    @Override
    public RoomNorm getRoomNormByRoomId(String roomId, String chargeId) {
        return roomNormMapper.getRoomNormByRoomId(roomId, chargeId);
    }

    @Override
    public List<RoomNorm> selectRoomNormByIds(String roomNormIds) {
        return roomNormMapper.selectRoomNormByIds(roomNormIds);
    }

    @Override
    public List<RoomNorm> selectKindRoomNorm(String nodeId) {
        return roomNormMapper.selectKindRoomNorm(nodeId);
    }

    @Override
    public List<NormChargeVo> selectArrearageRoomNorm(NormChargeVo normChargeVo) {
        List<NormChargeVo> normChargeVos = roomNormMapper.selectArrearageRoomNorm(normChargeVo);
        if (null != normChargeVos && normChargeVos.size() > 0) {
            List<ChargeTime> chargeTimes = chargeTimeService.selectChargeTimeList(new ChargeTime());
            Map<String, ChargeTime> chargeTimeMap = chargeTimes.stream().collect(Collectors.toMap(ChargeTime::getChartimId, item -> item));
            normChargeVos.stream().forEach(x -> {
                if (chargeTimeMap.containsKey(x.getChartimId())) {
                    x.setChargeTime(chargeTimeMap.get(x.getChartimId()));
                }
            });
        }
        return normChargeVos;
    }

    @Override
    public List<CurrentPeriodFeeVo> currentPeriodFee(CurrentPeriodFeeVo currentPeriodFeeVo) {
        return roomNormMapper.currentPeriodFee(currentPeriodFeeVo);
    }

    /**
     * 修改房屋收费标准
     *
     * @param roomNorm 房屋收费标准
     * @return 结果
     */
    @Override
    public int updateRoomNorm(RoomNorm roomNorm) {
        roomNorm.setUpdateTime(DateUtils.getNowDate());
        return roomNormMapper.updateRoomNorm(roomNorm);
    }

    /**
     * 批量删除房屋收费标准
     *
     * @param roomNormIds 需要删除的房屋收费标准ID
     * @return 结果
     */
    @Override
    public int deleteRoomNormByIds(String[] roomNormIds) {
        //判断该收费标准时候生成过账单，假如生成过账单的话不允许删除
//        for (int i = 0; i < roomNormIds.length; i++) {
//            RoomNorm roomNorm=roomNormMapper.selectRoomNormById(roomNormIds[i]);
//            RuleCost ruleCost=new RuleCost();
//            ruleCost.setRoomNormId(roomNorm.getRoomNormId());
//            List<RuleCost> ruleCostList= ruleCostMapper.selectRuleCostList(ruleCost);
//            if(ruleCostList!=null && ruleCostList.size()>0){
//                throw new BaseException("该房屋收费标准已生成过费用单,请勿删除");
//            }
//        }
        return roomNormMapper.deleteRoomNormByIds(roomNormIds);
    }

    /**
     * 删除房屋收费标准信息
     *
     * @param roomNormId 房屋收费标准ID
     * @return 结果
     */
    @Override
    public int deleteRoomNormById(String roomNormId) {
//        //判断该收费标准时候生成过账单，假如生成过账单的话不允许删除
//        RoomNorm roomNorm=roomNormMapper.selectRoomNormById(roomNormId);
//        RuleCost ruleCost=new RuleCost();
//        ruleCost.setRoomNormId(roomNorm.getRoomNormId());
//        List<RuleCost> ruleCostList= ruleCostMapper.selectRuleCostList(ruleCost);
//        if(ruleCostList!=null && ruleCostList.size()>0){
//            throw new BaseException("该房屋收费标准已生成过费用单,请勿删除");
//        }
        return roomNormMapper.deleteRoomNormById(roomNormId);
    }
}
